// ml278
// Copyright (C) 2008 Bjørn Øivind Bjørnsen, Aleksander Gjermundsen, Knut Andre Tidemann, Thomas Hansen
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

//
// Global variable definitions
//

uniform float fCameraHeightSqr;
uniform float fInnerRadius;
uniform float fKm4PI;
uniform float fKmESun;
uniform float fKr4PI;
uniform float fKrESun;
uniform float fOuterRadius;
uniform float fOuterRadiusSqr;
uniform float fScale;
uniform float fScaleOverScaleDepth;
uniform vec4 fvCameraPos;
uniform vec3 fvInvWavelengths;
uniform vec4 fvLightPos;
uniform mat4 matWorldViewProjection;

//
// Function declarations
//

float getNearIntersection( in vec3 v3Pos, in vec3 v3Ray, in float fDistance2, in float fRadius2 );
float scale( in float fCos );

//
// Function definitions
//

float getNearIntersection( in vec3 v3Pos, in vec3 v3Ray, in float fDistance2, in float fRadius2 ) {
    float B;
    float C;
    float fDet;

    B = (2.00000 * dot( v3Pos, v3Ray));
    C = (fDistance2 - fRadius2);
    fDet = max( 0.00000, ((B * B) - (4.00000 * C)));
    return (0.500000 * (( -B ) - sqrt( fDet )));
}


float scale( in float fCos ) {
    float x;

    x = (1.00000 - fCos);
    return (0.250000 * exp( (-0.00287000 + (x * (0.459000 + (x * (3.83000 + (x * (-6.80000 + (x * 5.25000)))))))) ));
}


void main() {
    vec3 fvPos;
    vec3 fvRay;
    float fFar;
    float fNear;
    vec3 fvStart;
    float fDepth;
    float fCameraAngle;
    float fLightAngle;
    float fCameraScale;
    float fLightScale;
    float fCameraOffset;
    float fTemp;
    float fSampleLength;
    float fScaledLength;
    vec3 fvSampleRay;
    vec3 fvSamplePoint;
    vec3 fvFrontColor = vec3( 0.00000, 0.00000, 0.00000);
    int i;
    float fHeight;
    float fSampleDepth;
    float fScatter;
    vec3 fvAttenuate;
    vec4 Position = gl_Vertex;
    vec2 Texcoord = vec2(gl_MultiTexCoord0);

    fvPos = Position.xyz ;
    fvRay = (fvPos - fvCameraPos.xyz );
    fvPos = normalize( fvPos );
    fFar = length( fvRay );
    fvRay /= fFar;
    fNear = getNearIntersection( vec3( fvCameraPos), fvRay, fCameraHeightSqr, fOuterRadiusSqr);
    fvStart = (vec3( fvCameraPos) + (fvRay * fNear));
    fFar -= fNear;
    fDepth = exp( ((fInnerRadius - fOuterRadius) * 4.00000) );
    fCameraAngle = (dot( ( -fvRay ), fvPos) / fFar);
    fLightAngle = (dot( fvLightPos.xyz , fvPos) / fFar);
    fCameraScale = scale( fCameraAngle);
    fLightScale = scale( fLightAngle);
    fCameraOffset = (fDepth * fCameraScale);
    fTemp = (fLightScale + fCameraScale);
    fSampleLength = (fFar / 3.00000);
    fScaledLength = (fSampleLength * fScale);
    fvSampleRay = (fvRay * fSampleLength);
    fvSamplePoint = (fvStart + (fvSampleRay * 0.500000));
    for ( i = 0; (i < 3); ( i++ )) {
        fHeight = length( fvSamplePoint );
        fSampleDepth = exp( (fScaleOverScaleDepth * (fInnerRadius - fHeight)) );
        fScatter = ((fSampleDepth * fTemp) - fCameraOffset);
        fvAttenuate = exp( (( -fScatter ) * ((fvInvWavelengths * fKr4PI) + fKm4PI)) );
        fvFrontColor += (fvAttenuate * (fSampleDepth * fScaledLength));
        fvSamplePoint += fvSampleRay;
    }
    gl_Position = vec4( matWorldViewProjection * Position );
    //gl_Position = ftransform();
    gl_TexCoord[0] = vec4( (fvFrontColor * ((fvInvWavelengths * fKrESun) + fKmESun)), 1.00000 );
    gl_TexCoord[1] = vec4( fvAttenuate, 1.00000 );
    gl_TexCoord[2] = vec4( Texcoord, 0.0, 0.0 );
}


